<?php

namespace tmcore\services\crud\generators;

use app\common\model\dict\DictData;
use tmcore\services\crud\UtilService;

class Model extends Generate
{
    /**
     * @var string
     */
    protected string $fileType = 'php';

    /**
     * 替换变量
     */
    public function replaceContent()
    {
        $search = [
            '{NAMESPACE}',
            '{USE}',
            '{TABLE_COMMENT}',
            '{CAMEL_TABLE_NAME}',
            '{DELETE_CONTENT}',
            '{JOIN_MODEL}',
            '{ATTR_MODEL}'
        ];

        $replace = [
            $this->getNameSpaceContent(),
            $this->getUseContent(),
            $this->getTableCommentContent(),
            $this->getCamelTableName(),
            $this->getDeleteContent(),
            $this->getJoinModelContent(),
            $this->setAttrContent(),
        ];

        $content = UtilService::replaceFileContent($search, $replace, $this->getStub('model'));

        $this->setContent($content);
    }

    /**
     * 返回模板路径
     * @param string $type
     * @return mixed|string|string[]
     */
    public function getStub(string $type = 'model')
    {
        $basePath = 'php/model/';

        $stubs = [
            'getAttr' => $this->getTplPath($basePath . 'getAttr'),
            'setAttr' => $this->getTplPath($basePath . 'setAttr'),
            'hasMany' => $this->getTplPath($basePath . 'hasMany'),
            'hasOne' => $this->getTplPath($basePath . 'hasOne'),
            'model' => $this->getTplPath($basePath . 'model'),
        ];

        return $type ? $stubs[$type] : $stubs;
    }

    /**
     * 设置文件路径
     */
    public function setFilePath()
    {
        $name = $this->getCamelTableName() . '.' . $this->fileType;
        $this->setCrudFileName($name);

        $module_path = $this->basePath . 'common/model/';
        if (!empty($this->classDir)) $module_path .= $this->classDir . '/';
        $this->setCrudModuleFilePath($module_path);

        $data_path = $this->crudDir . 'php/app/common/model/';
        if (!empty($this->classDir)) $data_path .= $this->classDir . '/';
        $this->setCrudDataFilePath($data_path);
    }

    /**
     * 获取命名空间模板内容
     * @return string
     */
    public function getNameSpaceContent()
    {
        if (!empty($this->classDir)) return "namespace app\\common\\model\\" . $this->classDir . ';';
        return "namespace app\\common\\model;";
    }

    /**
     * 获取描述内容
     * @return string
     */
    public function getTableCommentContent()
    {
        if (!empty($this->crudData['table_comment'])) {
            $tpl = $this->crudData['table_comment'] . '模型';
        } else {
            $tpl = $this->getCamelClassName() . '模型';
        }
        return $tpl;
    }

    /**
     * 引用内容
     * @return string
     */
    public function getUseContent()
    {
        $tpl = "";
        if ($this->deleteConfig['type']) $tpl .= "use think\\model\\concern\\SoftDelete;" . PHP_EOL;
        if (!empty($this->params['crud_column_check']['is_userSelect'])) $tpl .= "use app\\common\\model\\user\\User;" . PHP_EOL;
        if (!empty($this->params['crud_column_check']['is_areaSelect'])) $tpl .= "use app\\common\\model\\setting\\Area;" . PHP_EOL;
        return $tpl;
    }

    /**
     * 软删除内容
     * @return string
     */
    public function getDeleteContent()
    {
        $tpl = "";
        if ($this->deleteConfig['type']) {
            $tpl = "use SoftDelete;";
        }

        return $tpl;
    }

    /**
     * 关联模型内容
     * @return string
     */
    public function getJoinModelContent()
    {
        $tpl = '';
        if (!$this->joinConfig) return $tpl;

        foreach ($this->joinConfig as $config) {
            if (empty($config) || empty($config['name']) || empty($config['model'])) {
                continue;
            }

            $search = [
                '{JOIN_NAME}',
                '{JOIN_MODEL}',
                '{FOREIGN_KEY}',
                '{PRIMARY_KEY}',
            ];

            $replace = [
                UtilService::lcfirst(UtilService::studly($config['name'])),
                $config['model'],
                $config['foreign_key'],
                $config['primary_key'],
            ];

            // 拼接关联方法
            $tpl .= UtilService::replaceFileContent($search, $replace, $this->getStub($config['type'])) . PHP_EOL . PHP_EOL;
        }

        return $tpl;
    }

    /**
     * 设置字段获取器内容
     * @return string
     */
    protected function setAttrContent()
    {
        $tpl = '';

        foreach ($this->crudColumn as $item) {
            // 兼容 复选框 下拉框多选 省市区联动，根据逗号分隔数组
            if ($item['view_type'] == 'checkbox' || ($item['view_type'] == 'select' && !empty($item['extra']['multiple'])) || $item['view_type'] == 'areaSelect') {
                // 获取器
                $search = [
                    '{NAME}',
                    '{FIELD}',
                    '{CONTENT_PHP}',
                ];

                $replace = [
                    $this->getTableColumnComment($item['column_comment']),
                    UtilService::ucwords($item['column_name']),
                    $this->getAttrGetMultipleStr($item)
                ];

                // 拼接attr方法
                $tpl .= UtilService::replaceFileContent($search, $replace, $this->getStub('getAttr')) . PHP_EOL . PHP_EOL;

                // 设置器
                $search = [
                    '{NAME}',
                    '{FIELD}',
                    '{CONTENT_PHP}',
                ];

                $replace = [
                    $this->getTableColumnComment($item['column_comment']),
                    UtilService::ucwords($item['column_name']),
                    $this->getAttrSetMultipleStr($item)
                ];

                // 拼接attr方法
                $tpl .= UtilService::replaceFileContent($search, $replace, $this->getStub('setAttr')) . PHP_EOL . PHP_EOL;
            }

            // 用户信息框
            if ($item['view_type'] == 'userSelect') {
                $search = [
                    '{NAME}',
                    '{FIELD}',
                    '{CONTENT_PHP}',
                ];

                $replace = [
                    $this->getTableColumnComment($item['column_comment']),
                    UtilService::ucwords($item['column_name']) . $this->attrPrefix,
                    $this->getAttrUserSelectStr($item)
                ];

                // 拼接attr方法
                $tpl .= UtilService::replaceFileContent($search, $replace, $this->getStub('getAttr')) . PHP_EOL . PHP_EOL;
            }

            // 省市区联动
            if ($item['view_type'] == 'areaSelect') {
                $search = [
                    '{NAME}',
                    '{FIELD}',
                    '{CONTENT_PHP}',
                ];

                $replace = [
                    $this->getTableColumnComment($item['column_comment']),
                    UtilService::ucwords($item['column_name']) . $this->attrPrefix,
                    $this->getAttrAreaSelectStr($item)
                ];

                // 拼接attr方法
                $tpl .= UtilService::replaceFileContent($search, $replace, $this->getStub('getAttr')) . PHP_EOL . PHP_EOL;
            }

            // 检验是否关联数据字典
            if ($item['dict_type']) {

                $search = [
                    '{NAME}',
                    '{FIELD}',
                    '{CONTENT_PHP}',
                ];

                $replace = [
                    $this->getTableColumnComment($item['column_comment']),
                    UtilService::ucwords($item['column_name']) . $this->attrPrefix,
                    $this->getAttrDictStr($item)
                ];

                // 拼接attr方法
                $tpl .= UtilService::replaceFileContent($search, $replace, $this->getStub('getAttr')) . PHP_EOL . PHP_EOL;
            }

            // 检验是否关联扩展自定义字段
            if (!empty($item['extra']['list'])) {

                $search = [
                    '{NAME}',
                    '{FIELD}',
                    '{CONTENT_PHP}',
                ];

                $replace = [
                    $this->getTableColumnComment($item['column_comment']),
                    UtilService::ucwords($item['column_name']) . $this->attrPrefix,
                    $this->getAttrExtraStr($item)
                ];

                // 拼接attr方法
                $tpl .= UtilService::replaceFileContent($search, $replace, $this->getStub('getAttr')) . PHP_EOL . PHP_EOL;
            }

        }

        $tpl = substr($tpl, 0, -1);

        return $tpl;
    }

    /**
     * 拼接attr获取器多选字符串
     * @param $item
     * @return string
     */
    protected function getAttrGetMultipleStr($item)
    {
        $tab2 = UtilService::tab(2);
        $tab3 = UtilService::tab(3);
        return <<<CONTENT
if (strpos(\$data['{$item['column_name']}'], ',') !== false) {
{$tab3}return explode(',', \$data['{$item['column_name']}']);
{$tab2}} else {
{$tab3}return \$data['{$item['column_name']}'];
{$tab2}}
CONTENT;
    }

    /**
     * 拼接attr设置器多选字符串
     * @param $item
     * @return string
     */
    protected function getAttrSetMultipleStr($item)
    {
        $tab2 = UtilService::tab(2);
        $tab3 = UtilService::tab(3);
        return <<<CONTENT
if (is_array(\$data['{$item['column_name']}'])) {
{$tab3}return implode(',', \$data['{$item['column_name']}']);
{$tab2}} else {
{$tab3}return \$data['{$item['column_name']}'];
{$tab2}}
CONTENT;
    }

    /**
     * 拼接attr关联数据字典
     * @param $item
     * @return string
     */
    protected function getAttrDictStr($item)
    {
        if (empty($item['dict_type'])) return '';

        // 关联数据字典
        $list = DictData::where(['type_id' => $item['dict_type']])->field('id,name,value')->select();
        if (!$list) return '';

        $tab2 = UtilService::tab(2);
        $tab3 = UtilService::tab(3);

        $arr_str = '';
        $len = count($list);
        foreach ($list as $key => $value) {
            $attr_key = is_numeric($value['value'])?$value['value']:"'{$value['value']}'";
            $arr_str .= <<<CONTENT
{$tab3}{$attr_key} => '$value[name]',
CONTENT. ($key < ($len - 1) ? PHP_EOL : '');
        }

        if ($item['view_type'] == 'checkbox' || ($item['view_type'] == 'select' && !empty($item['extra']['multiple']))) {
            return <<<CONTENT
\$attrs = [
$arr_str
{$tab2}];
{$tab2}\$result = [];
{$tab2}\$arr = explode(',', \$data['{$item['column_name']}']);

{$tab2}foreach (\$arr as \$key => \$value) {
{$tab3}\$result[\$key] = \$attrs[\$value];
{$tab2}}

{$tab2}return \$result;
CONTENT;
        } else {
            return <<<CONTENT
\$attrs = [
$arr_str
{$tab2}];

{$tab2}return \$attrs[\$data['{$item['column_name']}']];
CONTENT;
        }
    }

    /**
     * 拼接attr关联扩展自定义字段
     * @param $item
     * @return string
     */
    protected function getAttrExtraStr($item)
    {
        if (empty($item['extra']['list'])) return '';

        // 关联扩展字段
        $list = $item['extra']['list'];
        if (!$list) return '';

        $tab2 = UtilService::tab(2);
        $tab3 = UtilService::tab(3);

        $arr_str = '';
        $len = count($list);
        foreach ($list as $key => $value) {
            $attr_key = is_numeric($value['value'])?$value['value']:"'{$value['value']}'";
            $arr_str .= <<<CONTENT
{$tab3}{$attr_key} => '$value[name]',
CONTENT. ($key < ($len - 1) ? PHP_EOL : '');
        }

        if ($item['view_type'] == 'checkbox' || ($item['view_type'] == 'select' && !empty($item['extra']['multiple']))) {
            return <<<CONTENT
\$attrs = [
$arr_str
{$tab2}];
{$tab2}\$result = [];
{$tab2}\$arr = explode(',', \$data['{$item['column_name']}']);

{$tab2}foreach (\$arr as \$key => \$value) {
{$tab3}\$result[\$key] = \$attrs[\$value];
{$tab2}}

{$tab2}return \$result;
CONTENT;
        } else {
            return <<<CONTENT
\$attrs = [
$arr_str
{$tab2}];

{$tab2}return \$attrs[\$data['{$item['column_name']}']];
CONTENT;
        }
    }

    /**
     * 拼接attr用户信息字符串
     * @param $item
     * @return string
     */
    protected function getAttrUserSelectStr($item)
    {
        $tab2 = UtilService::tab(2);
        $tab3 = UtilService::tab(3);
        $tab4 = UtilService::tab(4);
        return <<<CONTENT
\$arr = explode(',', \$data['{$item['column_name']}']);
{$tab2}\$result = [];

{$tab2}foreach (\$arr as \$key => \$value) {
{$tab3}if(\$value) {
{$tab4}\$row = User::where(['id' => \$value])->field('id, account, avatar')->findOrEmpty();
{$tab4}if(!\$row->isEmpty()) array_push(\$result, ['id' => \$row['id'], 'name' => \$row['account'], 'avatar' => \$row['avatar']]);
{$tab3}}
{$tab2}}

{$tab2}return \$result;
CONTENT;
    }

    /**
     * 拼接attr省市区联动信息字符串
     * @param $item
     * @return string
     */
    protected function getAttrAreaSelectStr($item)
    {
        $tab2 = UtilService::tab(2);
        $tab3 = UtilService::tab(3);
        $tab4 = UtilService::tab(4);
        return <<<CONTENT
\$arr = explode(',', \$data['{$item['column_name']}']);
{$tab2}\$result = [];

{$tab2}foreach (\$arr as \$key => \$value) {
{$tab3}if(\$value) {
{$tab4}\$row = Area::where(['code' => \$value])->field('id, code, name')->findOrEmpty();
{$tab4}if(!\$row->isEmpty()) array_push(\$result, ['id' => \$row['id'], 'code' => \$row['code'], 'name' => \$row['name']]);
{$tab3}}
{$tab2}}

{$tab2}return \$result;
CONTENT;
    }
}